package com.springcloud.order.service;

import com.hyr.springcloud.dto.OrderDTO;
import com.springcloud.order.dao.OrderInfoRepository;
import com.springcloud.order.demain.OrderInfo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jms.annotation.JmsListener;
import org.springframework.jms.core.JmsTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.ZonedDateTime;
import java.util.Date;
import java.util.List;

@Service
public class OrderService {
    @Autowired
    private JdbcTemplate jdbcTemplate;

    private static final Logger LOG = LoggerFactory.getLogger(OrderService.class);

    @Autowired
    private OrderInfoRepository orderInfoRepository;

    @Autowired
    private JmsTemplate jmsTemplate;


    @Transactional
    @JmsListener(destination = "order:locked" ,containerFactory="msgFactory")
    public void handleOrderNew(OrderDTO orderDTO){
        LOG.info("Get new order to create:{}",orderDTO);

        if (orderInfoRepository.findByToken(orderDTO.getToken())!= null){
            LOG.info("Msg alrady processed:{}",orderDTO);
        }else{
            OrderInfo order = newOrder(orderDTO);
            orderInfoRepository.save(order);
            orderDTO.setId(order.getId());
        }
        orderDTO.setStatus("NEW");
        jmsTemplate.convertAndSend("order:pay",orderDTO);
    }






    @Transactional
    @JmsListener(destination = "order:finish" ,containerFactory="msgFactory")
    public void handleOrderFinish(OrderDTO orderDTO){
        LOG.info("Get  order to finish:{}",orderDTO);
        OrderInfo order = orderInfoRepository.getOne(orderDTO.getId()) ;
        order.setStatus("FINISH");
        orderInfoRepository.save(order);
    }


    /**
     * order错误的情况
     * 1.一开始索票失败
     * 2.扣费失败后，解锁票，触发
     * 3.定时任务检测超时订单
     * 锁票失败
     * @param orderDTO
     */
    @Transactional
    @JmsListener(destination = "order:fail" ,containerFactory="msgFactory")
    public void handleOrderFail(OrderDTO orderDTO){
        LOG.info("Get  order to fail:{}",orderDTO);
        OrderInfo orderInfo ;
        if (orderDTO.getId() == 0){
            orderInfo = newOrder(orderDTO);
            orderInfo.setStatus("FAIL");
            orderInfo.setReason("TICKET_LOCK_FAIL");
        }else{
            orderInfo = orderInfoRepository.getOne(orderDTO.getId()) ;
            if (orderDTO.getStatus().equals("NOT_ENOUGH_BALANCE")){
                orderInfo.setReason("NOT_ENOUGH_BALANCE");
            }
            if (orderDTO.getStatus().equals("TIMEOUT")){
                orderInfo.setReason("TIMEOUT");
            }
        }
        orderInfo.setStatus("FAIL");
        orderInfoRepository.save(orderInfo);
    }



    public OrderInfo getOrder(String token){
        OrderInfo orderInfo = orderInfoRepository.findByToken(token);
        return orderInfo;
    }


    public OrderInfo newOrder(OrderDTO orderDTO){
        OrderInfo orderInfo = new OrderInfo();
        orderInfo.setToken(orderDTO.getToken());
        orderInfo.setAmount(orderDTO.getAmount());
        orderInfo.setTitle(orderDTO.getTitle());
        orderInfo.setTicketNum(orderDTO.getTicketNum());
        orderInfo.setUserinfoId(orderDTO.getUserinfoId());
        orderInfo.setStatus("NEW");
        orderInfo.setCreateDate(ZonedDateTime.now());
        return orderInfo;
    }

    @Scheduled(fixedDelay = 1000L)
    public void checkTimeoutOrders(){
        ZonedDateTime checkTime = ZonedDateTime.now().minusMinutes(1L);
        List<OrderInfo> orderInfos = orderInfoRepository.findAllByStatusAndCreateDateBefore("NEW",checkTime);
        orderInfos.forEach(orderInfo -> {
            LOG.error("Order timeout:{}",orderInfo);
            OrderDTO orderDTO = new OrderDTO();
            orderDTO.setId(orderInfo.getId());
            orderDTO.setTicketNum(orderInfo.getTicketNum());
            orderDTO.setToken(orderInfo.getToken());
            orderDTO.setAmount(orderInfo.getAmount());
            orderDTO.setTitle(orderInfo.getTitle());
            orderDTO.setUserinfoId(orderInfo.getUserinfoId());
            orderDTO.setStatus("TIMEOUT");

            jmsTemplate.convertAndSend("order:fail",orderDTO);
        });
    }

}
